package com.obas.business.component.tree{

   import com.obas.business.component.tree.treeclass.ErrorNode;
   import com.obas.business.component.tree.treeclass.LoadingNode;
   import com.obas.business.component.tree.treeclass.LoadingTreeNodeFactory;
   import com.obas.business.component.tree.treeclass.Node;
   import com.ease.component.controls.AutoSizeTree;
   import com.ease.component.controls.Menu;
   import com.ease.component.controls.menu.AdvancedMenu;
   import com.ease.component.controls.menu.MenuItem;
   import com.ease.component.events.AdvancedMouseEvent;

   import flash.display.DisplayObject;
   import flash.events.Event;
   import flash.events.MouseEvent;

   import mx.collections.ArrayCollection;
   import mx.containers.Canvas;
   import mx.controls.listClasses.IListItemRenderer;
   import mx.controls.listClasses.ListBaseContentHolder;
   import mx.core.Container;
   import mx.events.FlexEvent;
   import mx.events.ListEvent;
   import mx.events.MenuEvent;
   import mx.events.TreeEvent;

   public class LoadingTree extends AutoSizeTree {

      public static const MENUITEM_TYPE_REFRESH:String = "refresh";

      public var nodeFactory:LoadingTreeNodeFactory = new LoadingTreeNodeFactory();
      [Bindable]public var menuType:int = 1;
      public var rootNode:Node;
      protected var _menuMap:Object = new Object();

      private var _treeMenu:AdvancedMenu;
      private var _menuCav:Canvas;

      public function set menu(value:AdvancedMenu):void {
         this._treeMenu = value;
      }

      public function get menu():AdvancedMenu {
         return this._treeMenu;
      }

      /**
      * Constructor
      */
      public function LoadingTree() {
         super();
         doubleClickEnabled = true;

         _treeMenu = new AdvancedMenu();
         _treeMenu.dataProvider = new Array();
         _menuMap = new Object();

         addEventListener(ListEvent.ITEM_DOUBLE_CLICK, onItemDoubleClick);
         addEventListener(ListEvent.ITEM_CLICK, onSelectedItemChanged);
         addEventListener(MouseEvent.MOUSE_DOWN, onSelectedItemChanged);
         addEventListener(FlexEvent.VALUE_COMMIT, onSelectedItemChanged);
         addEventListener(ListEvent.CHANGE, onSelectedItemChanged);

         addEventListener(TreeEvent.ITEM_OPEN, onItemOpen);
         addEventListener(AdvancedMouseEvent.RIGHT_MOUSE_DOWN, onMenuSelectedHandler);
      }

      override protected function createChildren():void {
         super.createChildren();

         if (!_menuCav) {
            _menuCav = new Canvas();
            _menuCav.visible = false;
            _menuCav.includeInLayout = false;
            buildMenu(_menuCav);
            this.addChild(_menuCav);
         }
      }

      protected function buildMenu(container:Container):void {
      }

      protected function onMenuSelectedHandler(event:MouseEvent):void {
         var rightClickItem:Node = getItemUnderMouse(event.stageX, event.stageY,
                                              dataProvider as ArrayCollection);
         if (rightClickItem == null && selectedItem != rightClickItem) {
            selectedItems = [];
         }
         else if (selectedItem != rightClickItem) {
            selectedItem = rightClickItem;
         }
      }

      public function getItemUnderMouse(x:Number, y:Number, items:ArrayCollection):Node {
         for each(var item:* in items) {
            if (!(item is Node)) {
               continue;
            }

            var itemRenderer:IListItemRenderer = itemToItemRenderer(item) as IListItemRenderer;

            if (itemRenderer != null && (itemRenderer as DisplayObject).hitTestPoint(x, y)) {
               return item;
            } else if (item.children != null) {
               var node:Node = getItemUnderMouse(x, y, item.children);
               if (node != null) {
                  return node;
               }
            }
         }

         return null;
      }

      public function getListContent():ListBaseContentHolder {
         return listContent;
      }

      protected function onItemOpen(event:TreeEvent):void {
         var node:Node = event.item as Node;
         if (node is LoadingNode) {
            return;
         }

         if (!node.initialized) {
            fetchChildrenData(node);
         }
      }

      protected function onMenuItemClick(event:MenuEvent):void {
         var node:Node = selectedItem as Node;
         var item:MenuItem = event.item as MenuItem;

         if (item.clickEventType == MENUITEM_TYPE_REFRESH) {
            fetchChildrenData(node);
         }
      }

      protected function onItemDoubleClick(event:ListEvent):void {
      }

      protected function onSelectedItemChanged(event:Event):void {
         var selectedNode:Node = selectedItem as Node;

         if (!selectedNode || selectedNode is LoadingNode || selectedNode is ErrorNode) {
            flexContextMenu = null;
         }
         else {
            var entityMenu:Menu = getEntityMenuByNode(selectedNode);
            if (entityMenu){
               _treeMenu.removeEventListener(MenuEvent.ITEM_CLICK, onMenuItemClick);
               flexContextMenu = _treeMenu = entityMenu.menu;
               _treeMenu.addEventListener(MenuEvent.ITEM_CLICK, onMenuItemClick);
            }
            else {
               flexContextMenu = null;
            }
         }
      }

      public function fetchChildrenData(node:Node, showLoading:Boolean = true):void {
         if (showLoading) {
            addLoadingStat(node);
         }

         callRemoteService(node);
      }

      private function addLoadingStat(node:Node):void {
         if (!node.children) {
            node.children = new ArrayCollection();
         }
         node.children.removeAll();
         node.children.addItem(new LoadingNode());
         if (!isItemOpen(node)) {
            expandItem(node, true);
         }
      }

      protected function callRemoteService(node:Node):void {
      }

      public function addErrorStat(node:Node, error:String):void {
         node.children = new ArrayCollection();
         node.children.addItem(new ErrorNode(error));
      }

      protected function removeNodeStat(node:Node):void {
         node.children.removeAll();
      }

      public function appendChildren(result:ArrayCollection, parentNode:Node):void {
      }

      protected function getEntityMenuByNode(node:Node):Menu {
         var entityMenu:Menu = _menuMap.hasOwnProperty(node.type) ? _menuMap[node.type] : null;
         if (entityMenu != null) {
            entityMenu.treeMode = true;
            entityMenu.selectedItems = [node.entity];
         }
         return entityMenu;
      }

   }
}
